#region Copyright

// AUTHOR: Omar Zabala
// Copyright (c) 2011, TheShieldStore.com
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
// 
// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation
//  and/or other materials provided with the distribution. Neither the name of the TheShieldStore.com nor the names of its contributors may be used to endorse
//  or promote products derived from this software without specific prior written permission. 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
// AND ANY EXPRESS OR IMPLIED WARRANTIES,  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
//  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#endregion

using System;
using System.Threading;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;

namespace DisplayShield
{
    public class Joystick
    {
        public InterruptPort[] _js;

        public Joystick()
        {
            _js = new InterruptPort[5];
            _js[0] = new InterruptPort(Pins.GPIO_PIN_D6, true, Port.ResistorMode.PullUp,
                                       Port.InterruptMode.InterruptEdgeLevelLow);
            _js[0].OnInterrupt += Up_OnInterrupt;

            _js[1] = new InterruptPort(Pins.GPIO_PIN_D3, true, Port.ResistorMode.PullUp,
                                       Port.InterruptMode.InterruptEdgeLevelLow);
            _js[1].OnInterrupt += Left_OnInterrupt;

            _js[2] = new InterruptPort(Pins.GPIO_PIN_D2, true, Port.ResistorMode.PullUp,
                                       Port.InterruptMode.InterruptEdgeLevelLow);
            _js[2].OnInterrupt += Down_OnInterrupt;

            _js[3] = new InterruptPort(Pins.GPIO_PIN_D4, true, Port.ResistorMode.PullUp,
                                       Port.InterruptMode.InterruptEdgeLevelLow);
            _js[3].OnInterrupt += Right_OnInterrupt;

            _js[4] = new InterruptPort(Pins.GPIO_PIN_D5, true, Port.ResistorMode.PullUp,
                                       Port.InterruptMode.InterruptEdgeLevelLow);
            _js[4].OnInterrupt += Push_OnInterrupt;
        }

        private void Push_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            PushEventHandler handler = Push;
            var args = new JoystickEventArgs(data1, data2, time);
            if (handler != null) handler(this, args);
            Thread.Sleep(200);
            _js[4].ClearInterrupt();
        }

        private void Right_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            RightEventHandler handler = Right;
            var args = new JoystickEventArgs(data1, data2, time);
            if (handler != null) handler(this, args);
            Thread.Sleep(200);
            _js[3].ClearInterrupt();
        }

        private void Left_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            LeftEventHandler handler = Left;
            var args = new JoystickEventArgs(data1, data2, time);
            if (handler != null) handler(this, args);
            Thread.Sleep(200);
            _js[1].ClearInterrupt();
        }

        private void Down_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            DownEventHandler handler = Down;
            var args = new JoystickEventArgs(data1, data2, time);
            if (handler != null) handler(this, args);
            Thread.Sleep(200);
            _js[2].ClearInterrupt();
        }

        private void Up_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            UpEventHandler handler = Up;
            var args = new JoystickEventArgs(data1, data2, time);
            if (handler != null) handler(this, args);
            Thread.Sleep(200);
            _js[0].ClearInterrupt();
        }


        public event UpEventHandler Up;


        public event DownEventHandler Down;


        public event LeftEventHandler Left;


        public event RightEventHandler Right;


        public event PushEventHandler Push;


        public bool[] JoyStickValues()
        {
            return new[]
                       {
                           !_js[0].Read(), !_js[1].Read(), !_js[2].Read(), !_js[3].Read(),
                           !_js[4].Read()
                       };
        }

        public bool JoyStickValue(int id)
        {
            return !_js[id].Read();
        }
    }
    public delegate void RightEventHandler(object sender, JoystickEventArgs args);

    public delegate void PushEventHandler(object sender, JoystickEventArgs args);

    public delegate void LeftEventHandler(object sender, JoystickEventArgs args);

    public delegate void DownEventHandler(object sender, JoystickEventArgs args);

    public delegate void UpEventHandler(object sender, JoystickEventArgs args);
}